package org.social.manager;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.sojoys.artifact.tools.ToolError;
import org.bean.DungeonTeam;
import org.bean.DungeonTeamMember;
import org.bean.PlayerInfo;
import org.error.GameErrorCode;
import org.remote.game.RemoteGameServer;
import org.social.db.bean.PlayerMap;
import org.social.db.cache.PlayerMapCache;
import org.utils.RemoteUtil;

import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 组队副本管理器
 * Created by fxf on 2017/12/1.
 */
public class DungeonTeamManager {

    private DungeonTeamManager() {
    }

    /**
     * Map<teamId, team>
     */
    private static Map<Integer, DungeonTeam> teamMap = Maps.newConcurrentMap();

    private static AtomicInteger idCache = new AtomicInteger();


    public static DungeonTeam createTeam(PlayerInfo playerInfo, int dungeonLevelCid, boolean matching) {
        checkTeamMember(playerInfo.getPid());
        DungeonTeamMember teamMember = new DungeonTeamMember(playerInfo.getPid(),
                playerInfo.getLvl(),
                playerInfo.getFightPower(),
                playerInfo.getName(),
                playerInfo.getHelpHeroCid(),
                playerInfo.getServerId(),
                false,
                true);

        int id = idCache.incrementAndGet();
        DungeonTeam team = new DungeonTeam(id, dungeonLevelCid, matching);
        team.getMemberList().add(teamMember);

        teamMap.put(id, team);
        return team;
    }

    /**
     * 匹配队伍
     */
    public static DungeonTeam matching(int dungeonLevelCid, PlayerInfo playerInfo) {

        Optional<DungeonTeam> op = teamMap.values().stream()
                .filter(team -> team.getLevelCid() == dungeonLevelCid)
                .filter(team -> team.getMemberList().size() < 3)
                .findFirst();
        DungeonTeam team = op.get();
        ToolError.isAndTrue(GameErrorCode.NO_MATCHING_TEAM, "", team == null);
        DungeonTeamMember newMember = team.addMember( playerInfo);

        noticeNewMemberJoin(team, newMember);

        return team;
    }

    public static boolean ready(int teamId, int pid, boolean ready){
        DungeonTeam team = teamMap.get(teamId);
        ToolError.isAndTrue(GameErrorCode.NO_TEAM,"",team == null);
        DungeonTeamMember member = team.getMember(pid);
        member.setReady(ready);




        return ready;
    }

    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~private method~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    private static void checkTeamMember(int pid) {
        teamMap.values().forEach(team -> {
            team.getMemberList().forEach(member -> {
                ToolError.isAndTrue(GameErrorCode.PLAYER_IN_TEAM, "", pid == member.getPid());
            });
        });
    }

    /**
     * 通知有新成员加入
     */
    private static void noticeNewMemberJoin(DungeonTeam team, DungeonTeamMember newMember) {
        Map<String, List<Integer>> map = group(team, newMember);

        map.forEach((sid, pidList) -> {
            RemoteGameServer remoteGameServer = RemoteUtil.gameAsyn(sid);
            remoteGameServer.noticeNewMemberJoin(pidList, newMember);
        });
    }

    private static void noticeChangeReadyState(DungeonTeam team,DungeonTeamMember opMember, boolean ready){
        Map<String, List<Integer>> map = group(team, opMember);

        map.forEach((sid, pidList) -> {
            RemoteGameServer remoteGameServer = RemoteUtil.gameAsyn(sid);
            remoteGameServer.noticeNewMemberJoin(pidList, opMember);
        });
    }

    /**
     * 分组
     */
    private static Map<String, List<Integer>> group(DungeonTeam team) {
        return group(team,null);
    }

    /**
     * 分组，去掉动作发起member
     */
    private static Map<String, List<Integer>> group(DungeonTeam team, DungeonTeamMember newMember) {
        Map<String, List<Integer>> map = Maps.newHashMap();
        for (DungeonTeamMember member : team.getMemberList()) {
            if (member == newMember)
                continue;

            List<Integer> list = map.computeIfAbsent(member.getServerId(), k -> Lists.newArrayList());
            list.add(member.getPid());
        }
        return map;
    }



}
